import de.bezier.data.sql.*;

public class Data
{
  private int [] months;
  private int total;
  private int numOfMonth;
  private int numOfYear;
  private int yearBegin;
  private int monthBegin;
  private int numOfRating;
  private int maxTick;
  private double [] rating;
  private String [] ratingMovie;
  Data()
  {
    total = 0;
    numOfMonth =12; 
    numOfYear = 91;
    yearBegin = 1920;
    monthBegin = 1;
    months = new int [numOfMonth*numOfYear]; 
    numOfRating = 5;
    maxTick = 0;
    rating = new double[numOfYear*numOfRating];
    ratingMovie = new String [numOfYear*numOfRating];
    initialize();
  }
  
  public void copyData(Data right)
  {
    total = 0 ;
    for(int i = 0 ;i<numOfMonth*numOfYear;i++)
    {
      this.months[i] = right.getCountByIndex(i);
      total+= right.getCountByIndex(i);
    }
  }
  private void initialize()
  {
    for( int i = 0 ;i<numOfMonth*numOfYear;i++)
    {
      months[i] =0;
    }
    total =0;
  }
  private void initializeRating()
  {
    for(int i = 0 ;i<numOfYear*numOfRating;i++)
    {
      rating[i] =0;
      ratingMovie[i] = "No Movie";
    }
  }
  public void tick( int yr, int mon)
  {
    //println("year is "+yr+",month is "+mon);
    if( mon !=0)
    {
      months[getMonth(yr,mon)]++;
      if (months[getMonth(yr,mon)] > maxTick)
        maxTick = months[getMonth(yr,mon)];
      total++;
    }
  }
  //Check if ra is in the top five rating
  //return true if ra is higher than anyone of current rating values, rearrange rating array
  //return false if not.
  public boolean checkRating(int yr,double ra, String mo)
  {
    
    
    //In descending order,the highest is stored in rating[0];
    int flag = 10;
    for(int i =numOfRating-1;i>=0;i--)
    {
      //If identical movie exists, return false
      if(mo.equals(getRatingMovie(yr,i)) )
      {
        return false;
      }
      if( ra> getRating(yr,i) )
      {
        flag = i;
      }
    }    
    if( flag>=numOfRating)
    {
      return false;
    }
    else
    {
      for(int i = numOfRating-1;i>flag;i--)
      {
        setRating(yr,i,getRating(yr,i-1));  
        //rating[i]= rating[i-1];
        setRatingMovie(yr,i,getRatingMovie(yr,i-1));
          //ratingMovie[i]= ratingMovie[i-1];
      }
      setRating(yr,flag,ra);
      //rating[flag] = ra;
      setRatingMovie(yr,flag,mo);
      //ratingMovie[flag]= mo;
      //For test    
      
      return true;
    }
    
  }
  
  public void printRating()
  {
      for(int i = yearBegin;i<yearBegin+numOfYear;i++)
      {
        println("Year "+i+"s rating is ");
        for(int j = 0 ;j<numOfRating;j++)
        {
          print(getRating(i,j)+",name is "+getRatingMovie(i,j)+"   ");
        }
        println();
      } 
  }
  void setRating( int yr, int index,double rate)
  {
    rating[(yr-yearBegin)*numOfRating+index]= rate;
  }
  void setRatingMovie( int yr, int index, String name)
  {

    ratingMovie[(yr-yearBegin)*numOfRating+index]= name;
  }
  double getRating(int yr, int index)
  {
    return rating[(yr-yearBegin)*numOfRating+index];
  }
  String getRatingMovie(int yr, int index)
  {

    return ratingMovie[(yr-yearBegin)*numOfRating+index];
  }
  public int getCount(int yr, int mon)
  {
    return months[getMonth(yr,mon)];
  }
  public int getCountByIndex( int index)
  {
    return this.months[index];
  }
  public int getTotal()
  {
    return total;
  }
  public int getMax()
  {
    return maxTick;
  }
  private int getMonth( int yr, int mon)
  {
    return (yr-yearBegin)*numOfMonth +(mon-monthBegin);
  }
  public int getNumOfRating()
  {
    return numOfRating;
  }
  
  private String [] getRatingString()
  {
    float dateMin = filmTimeLine.getYearMin();
    float dateMax = filmTimeLine.getYearMax();
    int yearMin = int(dateMin);
    int yearMax = int(dateMax);
    if(yearMin<yearBegin)
     yearMin = yearBegin;
     if(yearMax>yearBegin+numOfYear-1)
     yearMax = yearBegin+numOfYear-1;
    //if( yearMin>yearMax)
      //return;
      
    String [] resRatingMovie = new String [numOfRating];
    double [] resRating = new double [numOfRating];
    int flag = 10;
    for( int i = yearMin;i<yearMax;i++)
    {
      for( int j = 0;j<numOfRating;j++)
      {
        //println("year "+i+"th "+j+"th Rating is "+getRating(i,j)+", Name is "+getRatingMovie(i,j));
        if( getRating(i,j)==0 || getRatingMovie(i,j).length()==0)
          break;
            for(int m =numOfRating-1;m>=0;m--)
            {
              if(getRatingMovie(i,j).equals(resRatingMovie[m]))
              {
                //do nothing
                break;
              }
              if(getRating(i,j)>resRating[m])
              {
                flag = m;
              }
            }
            if( flag>=numOfRating)
            {
              //do nothing
              break;
            }
            else
            {
              for(int k = numOfRating-1;k>flag;k--)
              {
                  resRating[k]= resRating[k-1];
                  resRatingMovie[k]= resRatingMovie[k-1];
              }
              resRating[flag] = getRating(i,j);
              resRatingMovie[flag]= getRatingMovie(i,j);;
            }
      }
    }
    for( int i = 0;i<numOfRating;i++)
    {
    println("rating["+i+"] is "+resRating[i]+", resRatingMovie is"+ resRatingMovie[i]);
    }
    
    String [] res= new String [numOfRating];
    int len1=39;
    int len2=5;
    String fillChar=" ";
    StringBuffer fillStr = new StringBuffer();
    String part1;
    String part2;
    int diff=0;   

    for (int i =0; i< numOfRating;i++)
    {       
          fillStr = new StringBuffer();
          if( resRatingMovie[i].length()<=40)
          {
          diff = len1 - resRatingMovie[i].length();
          for(int m =0;m<diff;m++)
            fillStr.append(fillChar);                      
            part1 = resRatingMovie[i]+fillStr;
          }
          else
            part1 = resRatingMovie[i].substring(0,38);
          //println("The "+i+"th string is "+ratingMovie[i]+", length() is "+ratingMovie[i].length()+", part1 is "+part1);
          diff = len2 - Double.toString(resRating[i]).length();
          fillStr = new StringBuffer();
          for( int m=0;m<diff;m++)
            fillStr.append(fillChar);
            //String part2 = fillStr+Double.toString(rating[i]);    
            part2 =" "+Double.toString(resRating[i]);      
            res[i]= part1+ part2;
        
      //print("********"+ratingMovie[i]+"*****"+Double.toString(rating[i]));
    }
    
    return res;
  }

}

public class DataAccess
{
   private ArrayList movies;
   private String genre;
   private Data oneGenre;
   private SQLite db;
   private String [] monthName={"January","February","March","April","May","June","July","August","September","October","November","December"};
   
   DataAccess(PApplet _papplet)
   {
      db = new SQLite( _papplet, "finalDB.db" );  // initialize database
      oneGenre = new Data();
   }
   
  
   
   /*
   public Data getDataByGenre(String genreName)
   {     
     
      this.genre = genreName; 
      oneGenre.initialize();
      oneGenre.initializeRating();
      if( db.connect() )  // if there is a connection
      {
        db.query("SELECT M.month AS month,M.year AS year,M.rating AS rating, M.movieName As movie, G.genreType As genre FROM movies M JOIN genres G WHERE M.id=G.movieID and G.genreType=\'"+genre+"\';");
        while (db.next())  // goes line by line through results from query
        {     
          
          int ye = db.getInt("year");
          //println("Month is "+db.getString("Month"));
          int mon = stringToInt( db.getString("month"));
          //println("Year is "+ye+", month is "+mon);          
          double rating = db.getDouble("rating");        
          String movie = new String(db.getString("movie"));
          String genre = new String(db.getString("genre"));         
          oneGenre.tick(ye,mon);
          oneGenre.checkRating(rating,movie);         
        }    
      }  
      println("finish searching!");
     return  oneGenre;    
   }
   */
   
   public void getAllGenreData(Data [] allData)
   {     
     
      //this.genre = genreName; 
      //oneGenre.initialize();
      //oneGenre.initializeRating();
      if( db.connect() )  // if there is a connection
      {
        db.query("SELECT M.month AS month,M.year AS year,M.rating AS rating, M.movieName As movie,G.genreType As genre FROM movies M JOIN genres G WHERE M.id=G.movieID;");
        while (db.next())  // goes line by line through results from query
        {          
          int ye = db.getInt("year");
          int mon = stringToInt( db.getString("month"));         
          double rating = db.getDouble("rating");          
          String movie = new String(db.getString("movie"));
          String genre = new String(db.getString("genre"));
          for( int i =0;i<allData.length;i++)
          {
            if( genre.equals(genreName[i]))
            {
              //println("The "+i+"th movie is "+genre);
              allData[i].tick(ye,mon);
              allData[i].checkRating(ye,rating,movie);
            }
          }                  
        }    
      }  
    // return  oneGenre;    
   }
   
   
   private int stringToInt( String mon)
   {
     for (int i = 0 ;i<12;i++)
     {
       //println("monthname[i] is"+monthName[i]);
       if( monthName[i].equals(mon) )
           return (i+1);
     }
     return 0;
   }
   
    ///
   /// Given a List to store Movies, and a year, this will find the most popular and highest rated Top 5 movies
   /// and return an arrayList of the movies
   public ArrayList<Movie> getTop5(String genre, ArrayList<Movie> movieList, int yearFrom, int yearTo)
   {
     movieList.clear();
     if(db.connect()){
       
       db.query("select M.movieName, M.rating, M.voteCount from movies M JOIN genres G where M.year>"+(yearFrom-1) + " and M.year<"+(yearTo+1) +
       " G.movieID = M and G.genreType = \""+genre+"\" and M.voteCount > 100000 ORDER BY M.rating DESC,M.voteCount DESC LIMIT 5 ;");
       
       while(db.next())
       {
         String movie = db.getString("movieName");
         double rating = db.getDouble("rating");
         int voteCount = db.getInt("voteCount");
         Movie m = new Movie(movie, rating, voteCount);
         movieList.add(m);
       }
       
     }
     System.out.println(movieList.get(0).movieName);
     return movieList;

   }

   

}





